﻿
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Dynamic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Web;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;

namespace CNative.Dapper.Utils
{
    /// <summary>
    /// XML工具类
    /// </summary>
    public static class XmlUtil
    {
        #region GetActionDesc
        /// <summary>
        /// 从XML读取注释
        /// </summary>
        /// <returns></returns>
        public static Dictionary<string, string> GetActionDesc()
        {
            Dictionary<string, string> result = new Dictionary<string, string>();

            string xmlPath = string.Format("{0}/{1}.XML", System.AppDomain.CurrentDomain.BaseDirectory, typeof(XmlUtil).Assembly.GetName().Name);
            if (File.Exists(xmlPath))
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.Load(xmlPath);

                XmlNode summaryNode; string type; string desc; int pos; string key;
                foreach (XmlNode node in xmlDoc.SelectNodes("//member"))
                {
                    type = type = node.Attributes["name"].Value;
                    if (type.StartsWith("M:PrisonWebApi.Controllers"))
                    {
                        pos = type.IndexOf("(");
                        if (pos == -1) pos = type.Length;
                        key = type.Substring(2, pos - 2);
                        summaryNode = node.SelectSingleNode("summary");
                        desc = summaryNode.InnerText.Trim();
                        result.Add(key, desc);
                    }
                }
            }

            return result;
        }
        #endregion
        #region XmlSerialize/DESerializer
        /// <summary>
        /// 将实体对象转换成XML
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="obj">实体对象</param>
        public static string XmlSerialize<T>(this T obj)
        {
            try
            {
                using (StringWriter sw = new StringWriter())
                {
                    Type t = obj.GetType();
                    var serializer = new XmlSerializer(obj.GetType());
                    serializer.Serialize(sw, obj);
                    sw.Close();
                    return sw.ToString();
                }
            }
            catch (Exception ex)
            {
                throw new Exception("将实体对象转换成XML异常", ex);
            }
        }

        /// <summary>
        /// 将XML转换成实体对象
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="strXML">XML</param>
        public static T DESerializer<T>(this string strXML) where T : class
        {
            try
            {
                using (var sr = new StringReader(strXML))
                {
                    var serializer = new XmlSerializer(typeof(T));
                    return serializer.Deserialize(sr) as T;
                }
            }
            catch (Exception ex)
            {
                throw new Exception("将XML转换成实体对象异常", ex);
            }
        }
        #endregion
        #region ConvertXMLToDataSet/ConvertDataSetToXML
        /// <summary>
        /// 将xml对象内容字符串转换为DataSet
        /// </summary>
        /// <param name="xmlData"></param>
        /// <returns></returns>
        public static DataSet ConvertXMLToDataSet(this string xmlData)
        {
            try
            {
                XmlDocument doc = new XmlDocument();
                doc.LoadXml(xmlData);
                var xmlDS = new DataSet();
                using (var stream = new StringReader(xmlData))
                //从stream装载到XmlTextReader
                using (var reader = new XmlTextReader(stream))
                {
                    xmlDS.ReadXml(reader);
                }
                return xmlDS;
            }
            catch (System.Exception exs)
            {
                try
                {
                    if (xmlData.Length > 0)
                        return ConvertXMLToDataSet(xmlData.Substring(1));
                    throw exs;
                }
                catch (System.Exception ex)
                {
                    throw ex;
                }
            }
        }

        /// <summary>
        /// 将xml文件转换为DataSet
        /// </summary>
        /// <param name="xmlFile"></param>
        /// <returns></returns>
        public static DataSet ConvertXMLFileToDataSet(this string xmlFile)
        {
            try
            {
                var xmld = new XmlDocument();
                xmld.Load(xmlFile);

                return ConvertXMLToDataSet(xmld.InnerXml);
            }
            catch (System.Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 将DataSet转换为xml对象字符串
        /// </summary>
        /// <param name="xmlDS"></param>
        /// <returns></returns>
        public static string ConvertDataSetToXML(this DataSet xmlDS)
        {
            try
            {
                using (var stream = new MemoryStream())
                //从stream装载到XmlTextReader
                using (var writer = new XmlTextWriter(stream, Encoding.Unicode))
                {
                    //用WriteXml方法写入文件.
                    xmlDS.WriteXml(writer);
                    int count = (int)stream.Length;
                    byte[] arr = new byte[count];
                    stream.Seek(0, SeekOrigin.Begin);
                    stream.Read(arr, 0, count);

                    var utf = new UnicodeEncoding();
                    return utf.GetString(arr).Trim();
                }
            }
            catch (System.Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// 将DataSet转换为xml文件
        /// </summary>
        /// <param name="xmlDS"></param>
        /// <param name="xmlFile"></param>
        public static void ConvertDataSetToXMLFile(this DataSet xmlDS, string xmlFile)
        {
            try
            {
                using (var stream = new MemoryStream())
                //从stream装载到XmlTextReader
                using (var writer = new XmlTextWriter(stream, Encoding.Unicode))
                {
                    //用WriteXml方法写入文件.
                    xmlDS.WriteXml(writer);
                    int count = (int)stream.Length;
                    byte[] arr = new byte[count];
                    stream.Seek(0, SeekOrigin.Begin);
                    stream.Read(arr, 0, count);

                    //返回Unicode编码的文本
                    var utf = new UnicodeEncoding();
                    var sw = new StreamWriter(xmlFile);
                    sw.WriteLine("<?xml version=\"1.0\\ encoding=\"utf - 8\"?>");
                    sw.WriteLine(utf.GetString(arr).Trim());
                }
            }
            catch (System.Exception ex)
            {
                throw ex;
            }
        }
        //======================================================================================================
        /// <summary>
        /// 将Xml字符串转换成DataTable对象
        /// </summary>
        /// <param name="xmlStr">Xml字符串</param>
        /// <param name="tableIndex">Table表索引</param>
        /// <returns>DataTable对象</returns>
        public static DataTable ConvertToDataTableByXmlStringIndex(this string xmlStr, int Index)
        {
            return ConvertToDateSetByXmlString(xmlStr).Tables[Index];
        }
        /// <summary>
        /// 将Xml字符串转换成DataTable对象 第一个Table
        /// </summary>
        /// <param name="xmlStr">Xml字符串</param>
        /// <returns>DataTable对象</returns>
        public static DataTable ConvertToDataTableByXmlString(this string xmlStr)
        {
            return ConvertToDateSetByXmlString(xmlStr).Tables[0];
        }

        /// <summary>
        /// 将XML字符串转换成DATASET
        /// </summary>
        /// <param name="xmlStr"></param>
        /// <returns></returns>
        public static DataSet ConvertToDateSetByXmlString(this string xmlStr)
        {
            if (xmlStr.Length > 0)
            {
                StringReader StrStream = null;
                XmlTextReader Xmlrdr = null;
                try
                {
                    DataSet ds = new DataSet();
                    //读取字符串中的信息
                    StrStream = new StringReader(xmlStr);
                    //获取StrStream中的数据
                    Xmlrdr = new XmlTextReader(StrStream);
                    //ds获取Xmlrdr中的数据  
                    //ds.ReadXmlSchema(Xmlrdr);
                    ds.ReadXml(Xmlrdr);
                    return ds;
                }
                catch (Exception e)
                {
                    try
                    {
                        if (xmlStr?.Length > 0)
                            return ConvertToDateSetByXmlString(xmlStr.Substring(1));

                        throw e;
                    }
                    catch (Exception ee)
                    {

                        throw ee;
                    }
                }
                finally
                {
                    //释放资源
                    if (Xmlrdr != null)
                    {
                        Xmlrdr.Close();
                        StrStream.Close();
                    }
                }
            }
            else
            {
                return null;
            }
        }
        //---------------------------------------------------------------------------------
        /// <summary>
        /// 将DATASET转换成XML字符串
        /// </summary>
        /// <param name="ds"></param>
        /// <returns></returns>
        public static string ConvertToXmlStringByDataSet(this DataSet ds)
        {
            return ConvertToXmlStringByDataSetIndex(ds, -1);
        }

        ///<summary>
        /// 将DataSet对象中指定的Table转换成XML字符串 当为-1时为第一个
        /// </summary>
        /// <param name="ds">DataSet对象</param>
        /// <param name="tableIndex">DataSet对象中的Table索引</param>
        /// <returns>XML字符串</returns>
        public static string ConvertToXmlStringByDataSetIndex(this DataSet ds, int Index)
        {
            if (ds == null || ds.Tables.Count == 0) return "";
            if (Index != -1 && Index < ds.Tables.Count)
            {
                return ConvertToXmlStringByDataTable(ds.Tables[Index]);
            }
            else
            {
                return ConvertToXmlStringByDataTable(ds.Tables[0]);
            }
        }

        /// <summary>
        /// 将DATATABLE转换成XML字符串
        /// </summary>
        /// <param name="dt"></param>
        /// <returns></returns>
        public static string ConvertToXmlStringByDataTable(this DataTable dt)
        {
            if (dt != null)
            {
                MemoryStream ms = null;
                XmlTextWriter XmlWt = null;
                try
                {
                    ms = new MemoryStream();
                    //根据ms实例化XmlWt
                    XmlWt = new XmlTextWriter(ms, Encoding.Unicode);
                    //获取ds中的数据
                    dt.WriteXml(XmlWt);
                    int count = (int)ms.Length;
                    byte[] temp = new byte[count];
                    ms.Seek(0, SeekOrigin.Begin);
                    ms.Read(temp, 0, count);
                    //返回Unicode编码的文本
                    UnicodeEncoding ucode = new UnicodeEncoding();
                    string returnValue = ucode.GetString(temp).Trim();
                    return returnValue;
                }
                catch (System.Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    //释放资源
                    if (XmlWt != null)
                    {
                        XmlWt.Close();
                        ms.Close();
                        ms.Dispose();
                    }
                }
            }
            else
            {
                return "";
            }
        }

        #endregion
        #region DataSetToList/DataRowToT
        /// <summary>        
        /// DataSetToList        
        /// </summary>         
        /// <typeparam name="T">转换类型</typeparam>        
        /// <param name="dataSet">数据源</param>        
        /// <param name="tableIndex">需要转换表的索引</param>       
        /// /// <returns>泛型集合</returns>
        public static List<T> DataSetToList<T>(this DataSet dataset, int tableIndex) where T : class, new()
        {
            //确认参数有效
            if (dataset == null || dataset.Tables.Count <= 0 || tableIndex < 0
                || tableIndex >= dataset.Tables.Count)
            {
                return null;
            }
            var dt = dataset.Tables[tableIndex];
            return ConvertToList<T>(dt);
        }
        /// <summary>        
        /// DataSetToList        
        /// </summary>         
        /// <typeparam name="T">转换类型</typeparam>        
        /// <param name="dataSet">数据源</param>        
        /// <param name="tableIndex">需要转换表的索引</param>       
        /// /// <returns>泛型集合</returns>
        public static List<T> DataSetToList<T>(this DataSet dataset, string tableName) where T : class, new()
        {
            //确认参数有效
            if (dataset == null || dataset.Tables.Count <= 0 || string.IsNullOrEmpty(tableName)
                || !dataset.Tables.Contains(tableName))
            {
                return null;
            }
            var dt = dataset.Tables[tableName];
            return ConvertToList<T>(dt);
        }
        /// <summary>
        /// DataTable到List<T>的转换
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <returns></returns>
        public static List<T> ConvertToList<T>(this DataTable source) where T : new()
        {
            return Fugle.Publics.BaseCode.FgFuncTable2Entity.DataTableToList<T>(source);
            //List<T> itemlist = null;
            //if (source == null || source.Rows.Count == 0)
            //{
            //    return itemlist;
            //}
            //itemlist = new List<T>();
            //T item = null;
            //foreach (DataRow dr in source.Rows)
            //{
            //    item = DataRowToT<T>(dr);
            //    if (item != null)
            //        itemlist.Add(item);
            //}

            //return itemlist;
        }
        /// <summary>
        /// DataRow到T的转换
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="source"></param>
        /// <returns></returns>
        public static T DataRowToT<T>(this DataRow source) where T : class, new()
        {
            return Fugle.Publics.BaseCode.FgFuncTable2Entity.DataRowToEntity<T>(source);
            //T item = null;
            //if (source == null)
            //{
            //    return item;
            //}
            //item = new T();
            //Type targettype = typeof(T);
            //Type ptype = null;
            //Object value = null;

            //foreach (var pi in targettype.GetProperties())
            //{
            //    if (pi.CanWrite && source.Table.Columns.Contains(pi.Name))
            //    {
            //        try
            //        {
            //            ptype = Type.GetType(pi.PropertyType.FullName);
            //            value = Convert.ChangeType(source[pi.Name], ptype);
            //            pi.SetValue(item, value, null);
            //        }
            //        catch { }
            //    }
            //}
            //return item;
        }
        #endregion
        //-------------------------------------------------------------------------------------------
        #region Table2XmlData/Table2XmlDoc/Table2DicList/XmlNodes2Dic
        /// <summary>
        /// 根据表格 生成xml串
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="mark_table">表标签</param>
        /// <param name="mark_row">行标签</param>
        /// <param name="columnName">指定列；不为空，则只生成该列的数据</param>
        /// <returns></returns>
        public static string Table2XmlData(this DataTable dt, string mark_table, string mark_row = null, string columnName = null)
        {
            StringBuilder strXml = new StringBuilder();

            if (!string.IsNullOrEmpty(mark_table))//表标签
                strXml.AppendLine("<" + mark_table + ">");
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                if (!string.IsNullOrEmpty(mark_row))//行标签
                    strXml.AppendLine("<" + mark_row + ">");

                if (!string.IsNullOrEmpty(columnName) && dt.Columns.Contains(columnName))//指定列标签
                {
                    if (Convert.ToString(dt.Rows[i][columnName]) != "")
                        strXml.AppendLine("<" + columnName + ">" + dt.Rows[i][columnName] + "</" + columnName + ">");
                }
                else
                {
                    for (int j = 0; j < dt.Columns.Count; j++)
                    {
                        if (Convert.ToString(dt.Rows[i][j]) != "")
                            strXml.AppendLine("<" + dt.Columns[j].ColumnName + ">" + dt.Rows[i][j] + "</" + dt.Columns[j].ColumnName + ">");
                    }
                }
                if (!string.IsNullOrEmpty(mark_row))
                    strXml.AppendLine("</" + mark_row + ">");
            }
            if (!string.IsNullOrEmpty(mark_table))
                strXml.AppendLine("</" + mark_table + ">");

            return strXml.ToString();
        }
        /// <summary>
        /// 根据表格 生成XmlDocument
        /// </summary>
        public static XmlDocument Table2XmlDoc(this DataTable _dt, XmlDocument xmlDoc, string xpath, string xmlNodeName)
        {
            if (_dt != null && _dt.Rows.Count > 0 && xmlDoc != null)
            {
                var xmlNode = xmlDoc.SelectSingleNode(xpath);
                if (xmlNode != null)
                {
                    foreach (DataRow _dr in _dt.Rows)
                    {
                        xmlNode.AppendChild(_dr.DataRow2XmlNode(xmlDoc, xmlNodeName));
                    }
                }
            }
            return xmlDoc;
        }
        public static XmlNode DataRow2XmlNode(this DataRow _dr, XmlDocument xmlDoc, string xmlNodeName)
        {
            var _rowX = xmlDoc.CreateElement(xmlNodeName);
            if (_dr != null && _dr.Table.Columns != null)
            {
                for (int i = 0; i < _dr.Table.Columns.Count; i++)
                {
                    var item = xmlDoc.CreateElement(_dr.Table.Columns[i].ColumnName);
                    item.InnerText = Fugle.Publics.BaseCode.FgFuncStr.NullToStr( _dr[i]);
                    _rowX.AppendChild(item);
                }
            }
            return _rowX;
        }
        /// <summary>
        /// 把一行数据添加到指定节点中
        /// </summary>
        /// <param name="_dr"></param>
        /// <param name="xmlDoc"></param>
        /// <param name="xpath"></param>
        /// <returns></returns>
        public static XmlDocument DataRowUpdateXmlNode(this DataRow _dr, XmlDocument xmlDoc, string xpath)
        {
            if (_dr != null && _dr.Table.Columns != null)
            {
                var _rowNode = xmlDoc.SelectSingleNode(xpath);
                if (_rowNode != null)
                {
                    for (int i = 0; i < _dr.Table.Columns.Count; i++)
                    {
                        var item = xmlDoc.CreateElement(_dr.Table.Columns[i].ColumnName);
                        item.InnerText = Fugle.Publics.BaseCode.FgFuncStr.NullToStr(_dr[i]);
                        _rowNode.AppendChild(item);
                    }
                }
            }
            return xmlDoc;
        }
        public static Dictionary<string, string> DataRow2Dic(this DataRow _dr)
        {
            var _drdic = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

            if (_dr != null && _dr.Table.Columns != null)
            {
                for (int i = 0; i < _dr.Table.Columns.Count; i++)
                {
                    _drdic[_dr.Table.Columns[i].ColumnName] = Fugle.Publics.BaseCode.FgFuncStr.NullToStr(_dr[i]);
                }
            }
            return _drdic;
        }
        public static List<Dictionary<string, string>> Table2DicList(this DataTable _dt)
        {
            List<Dictionary<string, string>> _lsElt = new List<Dictionary<string, string>>();
            if (_dt != null && _dt.Rows.Count > 0)
            {
                foreach (DataRow _dr in _dt.Rows)
                {
                    var lst = DataRow2Dic(_dr);
                    if (lst?.Count > 0)
                        _lsElt.Add(lst);
                }
            }
            return _lsElt;
        }

        public static Dictionary<string, string> XmlNodes2Dic(this System.Xml.XmlNode[] narr)
        {
            var _conditionDic = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
            if (narr != null && narr.Length > 0)
            {
                for (var i = 0; i < narr.Length; i++)
                {
                    _conditionDic[narr[i].Name] = narr[i].InnerText;
                }
            }
            return _conditionDic;
        }
        #endregion

        #region T2XML/LT2XML /XML2T/XML2LT
        public static string T2XML<T>(this T pT)
        {
            if (pT == null) return null;
            XmlSerializer serializer = new XmlSerializer(typeof(T));
            MemoryStream stream = new MemoryStream();
            XmlTextWriter xtw = new XmlTextWriter(stream, Encoding.UTF8);
            xtw.Formatting = Formatting.Indented;
            try
            {
                serializer.Serialize(stream, pT);
            }
            catch (Exception ex)
            {
                new Fugle.Publics.sBaseClass.FgLogHelperPro("Error").Write.Error("序列化XML失败,类型:" + typeof(T), ex);
                return null;
            }

            stream.Position = 0;
            StringBuilder lbreturnStr = new StringBuilder();
            using (StreamReader sr = new StreamReader(stream, Encoding.UTF8))
            {
                string line = "";
                while ((line = sr.ReadLine()) != null)
                {
                    lbreturnStr.Append(line);
                }
            }
            return lbreturnStr.ToString();
        }
        /// <summary>
        /// 对象到XML-----泛类型
        /// </summary>
        /// <typeparam name="T">泛型对象</typeparam>
        /// <param name="pLT">泛型集合</param>
        /// <returns>XML</returns>
        public static string LT2XML<T>(this List<T> pLT)
        {
            if (pLT == null) return null;
            XmlSerializer serializer = new XmlSerializer(typeof(List<T>));
            MemoryStream stream = new MemoryStream();
            XmlTextWriter xtw = new XmlTextWriter(stream, Encoding.UTF8);
            xtw.Formatting = Formatting.Indented;
            try
            {
                serializer.Serialize(stream, pLT);
            }
            catch (Exception ex)
            {
                new Fugle.Publics.sBaseClass.FgLogHelperPro("Error").Write.Error("序列化XML失败,类型:" + typeof(T),ex);
                return null;
            }

            stream.Position = 0;
            StringBuilder lbreturnStr = new StringBuilder();
            using (StreamReader sr = new StreamReader(stream, Encoding.UTF8))
            {
                string line = "";
                while ((line = sr.ReadLine()) != null)
                {
                    lbreturnStr.Append(line);
                }
            }
            return lbreturnStr.ToString();
        }

        /// <summary>
        /// XML到反序列化到对象----支持泛类型
        /// </summary>
        /// <typeparam name="T">泛型类型</typeparam>
        /// <param name="psXML">XML数据</param>
        /// <returns>返回泛型实体</returns>
        public static T XML2T<T>(this string psXML)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                using (StreamWriter sw = new StreamWriter(stream, Encoding.UTF8))
                {
                    sw.Write(psXML);
                    sw.Flush();
                    stream.Seek(0, SeekOrigin.Begin);
                    XmlSerializer serializer = new XmlSerializer(typeof(T));
                    try
                    {
                        return ((T)serializer.Deserialize(stream));
                    }
                    catch (Exception ex)
                    { return default(T); }

                }
            }
        }

        /// <summary>
        /// XML到反序列化到对象----支持泛类型
        /// </summary>
        /// <typeparam name="T">泛型类型</typeparam>
        /// <param name="psXML">XML数据</param>
        /// <returns>返回泛型实体</returns>
        public static List<T> XML2LT<T>(this string psXML)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                using (StreamWriter sw = new StreamWriter(stream, Encoding.UTF8))
                {
                    sw.Write(psXML);
                    sw.Flush();
                    stream.Seek(0, SeekOrigin.Begin);
                    XmlSerializer serializer = new XmlSerializer(typeof(List<T>));
                    try
                    {
                        return ((List<T>)serializer.Deserialize(stream));
                    }
                    catch (Exception ex)
                    { return default(List<T>); }

                }
            }
        }
        #endregion

        #region XDocument
        /// <summary>
        /// 获取某节点存在量
        /// </summary>
        /// <returns></returns>
        public static int GetXmlNodeCount(string _xmlStr, string _nodeName)
        {
            try
            {
                XDocument _xdoc = XDocument.Parse(_xmlStr);
                var _nodes = _xdoc.Descendants(_nodeName).ToList();
                if (_nodes.Count > 0)
                    return _nodes.Count;
                else
                    return 0;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// 判断是否存在指定节点
        /// </summary>
        public static bool IsExistedNode(string _xmlStr, string _nodeName)
        {
            try
            {
                return GetXmlNodeCount(_xmlStr, _nodeName) > 0;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// 获取指定节点的值
        /// </summary>
        /// <param name="_xml">xml字符串</param>
        /// <param name="_node">节点名</param>
        public static List<string> GetXmlNodeValue(string _xmlStr, string _nodeName)
        {
            try
            {
                XDocument _xdoc = XDocument.Parse(_xmlStr);
                var _nodes = _xdoc.Descendants(_nodeName).ToList();
                if (_nodes.Count > 0)
                    return _nodes.Select(s => s.Value).ToList();
                else
                    return new List<string>();
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// 获取具有指定的 System.Xml.Linq.XName 的第一个（按文档顺序）子元素
        /// </summary>
        /// <param name="xmlElement">X节点</param>
        /// <param name="subElementName">要匹配xmlElementName子元素名称</param>
        /// <returns>返回子元素值</returns>
        public static string GetXElementValue(this System.Xml.Linq.XElement xmlElement, string subElementName, string defValue = "")
        {
            try
            {
                if (xmlElement != null && xmlElement.HasElements)
                {
                    var Attr = xmlElement.Element(subElementName);
                    if (Attr != null)
                    {
                        var val = Attr.Value;
                        if (!string.IsNullOrWhiteSpace(val)) return val;
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return defValue;
        }
        #endregion

        #region XmlDocument 文档创建
        /// <summary>
        /// 创建一个带有根节点的Xml文件
        /// </summary>
        /// <param name="xmlData">Xml数据</param>
        ///<returns></returns>
        public static XmlDocument CreateXmlDocumentByXmlData(string xmlData)
        {
            xmlData = XmlUtil.ReplaceXmlns(xmlData);
            var xmlDoc = new XmlDocument();
            xmlDoc.LoadXml(xmlData);
            return xmlDoc;
        }

        /// <summary>
        /// 创建一个XML文档
        /// </summary>
        /// <param name="rootNodeName">XML文档根节点名称(须指定一个根节点名称)</param>
        /// <param name="version">XML文档版本号(必须为:"1.0")</param>
        /// <param name="encoding">XML文档编码方式</param>
        /// <param name="standalone">该值必须是"yes"或"no",如果为null,Save方法不在XML声明上写出独立属性</param>
        /// <returns>成功返回true,失败返回false</returns>
        public static XmlDocument CreateXmlDocument(string rootNodeName, string version = "1.0", string encoding = "UTF-8", string standalone = "yes")
        {
            XmlDocument _xmlDocument = new XmlDocument();
            try
            {
                XmlDeclaration xmlDeclaration = _xmlDocument.CreateXmlDeclaration(version, encoding, standalone);
                XmlNode root = _xmlDocument.CreateElement(rootNodeName);
                _xmlDocument.AppendChild(xmlDeclaration);
                _xmlDocument.AppendChild(root);
            }
            catch (Exception ex)
            {
                throw ex; //这里可以定义你自己的异常处理
            }
            return _xmlDocument;
        }
        /// <summary>
        /// 创建一个XML文档
        /// </summary>
        /// <param name="xmlFileName">XML文档完全文件名(包含物理路径)</param>
        /// <param name="rootNodeName">XML文档根节点名称(须指定一个根节点名称)</param>
        /// <param name="version">XML文档版本号(必须为:"1.0")</param>
        /// <param name="encoding">XML文档编码方式</param>
        /// <param name="standalone">该值必须是"yes"或"no",如果为null,Save方法不在XML声明上写出独立属性</param>
        /// <returns>成功返回true,失败返回false</returns>
        public static bool CreateXmlDocument(string xmlFileName, string rootNodeName, string version = "1.0", string encoding = "UTF-8", string standalone = "yes")
        {
            bool isSuccess = false;
            try
            {
                var xmlDoc = CreateXmlDocument(rootNodeName, version, encoding, standalone);
                xmlDoc.Save(xmlFileName);
                isSuccess = true;
            }
            catch (Exception ex)
            {
                throw ex; //这里可以定义你自己的异常处理
            }
            return isSuccess;
        }


        /// <summary>
        /// 依据匹配XPath表达式的第一个节点来创建它的子节点(如果此节点已存在则追加一个新的同名节点
        /// </summary>
        /// <param name="xmlFileName">XML文档完全文件名(包含物理路径)</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名</param>
        /// <param name="xmlNodeName">要匹配xmlNodeName的节点名称</param>
        /// <param name="innerText">节点文本值</param>
        /// <param name="xmlAttributeName">要匹配xmlAttributeName的属性名称</param>
        /// <param name="value">属性值</param>
        /// <returns>成功返回true,失败返回false</returns>
        public static bool CreateXmlNodeByXPath(string xmlFileName, string xpath, string xmlNodeName, string innerText, string xmlAttributeName, string value)
        {
            bool isSuccess = false;
            XmlDocument xmlDoc = new XmlDocument();
            try
            {
                xmlDoc.Load(xmlFileName); //加载XML文档
                isSuccess = CreateXmlNodeByXPath(xmlDoc, xpath, xmlNodeName, innerText, xmlAttributeName, value);
                xmlDoc.Save(xmlFileName); //保存到XML文档
            }
            catch (Exception ex)
            {
                throw ex; //这里可以定义你自己的异常处理
            }
            return isSuccess;
        }

        /// <summary>
        /// 依据匹配XPath表达式的第一个节点来创建它的子节点(如果此节点已存在则追加一个新的同名节点
        /// </summary>
        /// <param name="_xmlDocument">XML文档完全文件名(包含物理路径)</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名</param>
        /// <param name="xmlNodeName">要匹配xmlNodeName的节点名称</param>
        /// <param name="innerText">节点文本值</param>
        /// <param name="xmlAttributeName">要匹配xmlAttributeName的属性名称</param>
        /// <param name="value">属性值</param>
        /// <returns>成功返回true,失败返回false</returns>
        public static bool CreateXmlNodeByXPath(XmlDocument _xmlDocument, string xpath, string xmlNodeName, string innerText, string xmlAttributeName, string value)
        {
            bool isSuccess = false;
            try
            {
                XmlNode xmlNode = _xmlDocument.SelectSingleNode(xpath);
                if (xmlNode != null)
                {
                    //存不存在此节点都创建
                    XmlElement subElement = _xmlDocument.CreateElement(xmlNodeName);
                    subElement.InnerXml = innerText;

                    //如果属性和值参数都不为空则在此新节点上新增属性
                    if (!string.IsNullOrEmpty(xmlAttributeName) && !string.IsNullOrEmpty(value))
                    {
                        XmlAttribute xmlAttribute = _xmlDocument.CreateAttribute(xmlAttributeName);
                        xmlAttribute.Value = value;
                        subElement.Attributes.Append(xmlAttribute);
                    }

                    xmlNode.AppendChild(subElement);
                }
                isSuccess = true;
            }
            catch (Exception ex)
            {
                throw ex; //这里可以定义你自己的异常处理
            }
            return isSuccess;
        }
        #endregion
        #region XmlDocument 文档节点或属性的添加、修改
        /// <summary>
        /// 依据匹配XPath表达式的第一个节点来创建或更新它的子节点(如果节点存在则更新,不存在则创建)
        /// </summary>
        /// <param name="_xmlDocument">XML文档完全文件名(包含物理路径)</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名</param>
        /// <param name="xmlNodeName">要匹配xmlNodeName的节点名称</param>
        /// <param name="innerText">节点文本值</param>
        /// <returns>成功返回true,失败返回false</returns>
        public static bool CreateOrUpdateXmlNodeByXPath(this XmlDocument _xmlDocument, string xpath, string xmlNodeName, string innerText)
        {
            bool isSuccess = false;
            bool isExistsNode = false;//标识节点是否存在
            try
            {
                var xmlNode = _xmlDocument.SelectSingleNode(xpath);
                if (xmlNode != null)
                {
                    //遍历xpath节点下的所有子节点
                    foreach (XmlNode node in xmlNode.ChildNodes)
                    {
                        if (node.Name.ToLower() == xmlNodeName.ToLower())
                        {
                            //存在此节点则更新
                            node.InnerXml = innerText;
                            isExistsNode = true;
                            break;
                        }
                    }
                    if (!isExistsNode)
                    {
                        //不存在此节点则创建
                        var subElement = _xmlDocument.CreateElement(xmlNodeName);
                        subElement.InnerXml = innerText;
                        xmlNode.AppendChild(subElement);
                    }
                }
                isSuccess = true;
            }
            catch (Exception ex)
            {
                throw ex; //这里可以定义你自己的异常处理
            }
            return isSuccess;
        }
        /// <summary>
        /// 依据匹配XPath表达式的第一个节点来创建或更新它的子节点(如果节点存在则更新,不存在则创建)
        /// </summary>
        /// <param name="xmlFileName">XML文档完全文件名(包含物理路径)</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名</param>
        /// <param name="xmlNodeName">要匹配xmlNodeName的节点名称</param>
        /// <param name="innerText">节点文本值</param>
        /// <returns>成功返回true,失败返回false</returns>
        public static bool CreateOrUpdateXmlNodeByXPath(string xmlFileName, string xpath, string xmlNodeName, string innerText)
        {
            bool isSuccess = false;
            XmlDocument xmlDoc = new XmlDocument();
            try
            {
                xmlDoc.Load(xmlFileName); //加载XML文档
                isSuccess = CreateOrUpdateXmlNodeByXPath(xmlDoc, xpath, xmlNodeName, innerText);
                xmlDoc.Save(xmlFileName); //保存到XML文档
            }
            catch (Exception ex)
            {
                throw ex; //这里可以定义你自己的异常处理
            }
            return isSuccess;
        }


        /// <summary>
        /// 依据匹配XPath表达式的第一个节点来创建或更新它的属性(如果属性存在则更新,不存在则创建)
        /// </summary>
        /// <param name="_xmlDocument">XML文档完全文件名(包含物理路径)</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名</param>
        /// <param name="xmlAttributeName">要匹配xmlAttributeName的属性名称</param>
        /// <param name="value">属性值</param>
        /// <returns>成功返回true,失败返回false</returns>
        public static bool CreateOrUpdateXmlAttributeByXPath(this XmlDocument _xmlDocument, string xpath, string xmlAttributeName, string value)
        {
            bool isSuccess = false;
            bool isExistsAttribute = false;//标识属性是否存在
            try
            {
                XmlNode xmlNode = _xmlDocument.SelectSingleNode(xpath);
                if (xmlNode != null)
                {
                    //遍历xpath节点中的所有属性
                    foreach (XmlAttribute attribute in xmlNode.Attributes)
                    {
                        if (attribute.Name.ToLower() == xmlAttributeName.ToLower())
                        {
                            //节点中存在此属性则更新
                            attribute.Value = value;
                            isExistsAttribute = true;
                            break;
                        }
                    }
                    if (!isExistsAttribute)
                    {
                        //节点中不存在此属性则创建
                        XmlAttribute xmlAttribute = _xmlDocument.CreateAttribute(xmlAttributeName);
                        xmlAttribute.Value = value;
                        xmlNode.Attributes.Append(xmlAttribute);
                    }
                }
                isSuccess = true;
            }
            catch (Exception ex)
            {
                throw ex; //这里可以定义你自己的异常处理
            }
            return isSuccess;
        }
        /// <summary>
        /// 依据匹配XPath表达式的第一个节点来创建或更新它的属性(如果属性存在则更新,不存在则创建)
        /// </summary>
        /// <param name="xmlFileName">XML文档完全文件名(包含物理路径)</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名</param>
        /// <param name="xmlAttributeName">要匹配xmlAttributeName的属性名称</param>
        /// <param name="value">属性值</param>
        /// <returns>成功返回true,失败返回false</returns>
        public static bool CreateOrUpdateXmlAttributeByXPath(string xmlFileName, string xpath, string xmlAttributeName, string value)
        {
            bool isSuccess = false;
            XmlDocument xmlDoc = new XmlDocument();
            try
            {
                xmlDoc.Load(xmlFileName); //加载XML文档
                isSuccess = CreateOrUpdateXmlAttributeByXPath(xmlDoc, xpath, xmlAttributeName, value);
                xmlDoc.Save(xmlFileName); //保存到XML文档
            }
            catch (Exception ex)
            {
                throw ex; //这里可以定义你自己的异常处理
            }
            return isSuccess;
        }

        /// <summary>
        /// 对象到XML-----泛类型
        /// </summary>
        /// <typeparam name="T">泛型类型</typeparam>
        /// <param name="pT">对象</param>
        /// <returns>XML</returns>
        private static string ReplaceXmlns(string xml)
        {
            if (xml == null) return null;
            if (xml.IndexOf("xmlns=", StringComparison.OrdinalIgnoreCase) > 0)
            {
                //xml = System.Text.RegularExpressions.Regex.Replace(xml,
                //@"(xmlns[^=]*=[""][^""]*[""])", "",
                //System.Text.RegularExpressions.RegexOptions.IgnoreCase |
                //System.Text.RegularExpressions.RegexOptions.Multiline);

                xml = System.Text.RegularExpressions.Regex.Replace(xml,
                   @"(xmlns:*[^=]*=[""][^""]*[""])", "",
                   System.Text.RegularExpressions.RegexOptions.IgnoreCase |
                   System.Text.RegularExpressions.RegexOptions.Multiline);

                xml = System.Text.RegularExpressions.Regex.Replace(xml,
                  @"(xsi:*[^=]*=[""][^""]*[""])", "",
                  System.Text.RegularExpressions.RegexOptions.IgnoreCase |
                  System.Text.RegularExpressions.RegexOptions.Multiline);
            }
            return xml;
        }
        #endregion
        #region XmlDocument 文档节点查询和读取
        /// <summary>
        /// 选择匹配XPath表达式的第一个节点XmlNode.
        /// </summary>
        /// <param name="xmlFileName">XML文档完全文件名(包含物理路径)</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名")</param>
        /// <returns>返回XmlNode</returns>
        public static XmlNode GetXmlNodeByXpath(this XmlDocument _xmlDocument, string xpath)
        {
            try
            {
                XmlNode xmlNode = _xmlDocument.SelectSingleNode(xpath);
                return xmlNode;
            }
            catch (Exception)
            {
                return null;
                //throw ex; //这里可以定义你自己的异常处理
            }
        }
        /// <summary>
        /// 选择匹配XPath表达式的第一个节点XmlNode.
        /// </summary>
        /// <param name="xmlFileName">XML文档完全文件名(包含物理路径)</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名")</param>
        /// <returns>返回XmlNode</returns>
        public static XmlNode GetXmlNodeByXpath(string xmlFileName, string xpath)
        {
            try
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.Load(xmlFileName); //加载XML文档
                return GetXmlNodeByXpath(xmlDoc, xpath);
            }
            catch (Exception)
            {
                return null;
                //throw ex; //这里可以定义你自己的异常处理
            }
        }

        /// <summary>
        /// 选择匹配XPath表达式的节点列表XmlNodeList.
        /// </summary>
        /// <param name="xmlFileName">XML文档完全文件名(包含物理路径)</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名")</param>
        /// <returns>返回XmlNodeList</returns>
        public static XmlNodeList GetXmlNodeListByXpath(this XmlDocument _xmlDocument, string xpath)
        {
            try
            {
                XmlNodeList xmlNodeList = _xmlDocument.SelectNodes(xpath);
                return xmlNodeList;
            }
            catch (Exception)
            {
                return null;
                //throw ex; //这里可以定义你自己的异常处理
            }
        }
        /// <summary>
        /// 选择匹配XPath表达式的节点列表XmlNodeList.
        /// </summary>
        /// <param name="xmlFileName">XML文档完全文件名(包含物理路径)</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名")</param>
        /// <returns>返回XmlNodeList</returns>
        public static XmlNodeList GetXmlNodeListByXpath(string xmlFileName, string xpath)
        {
            try
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.Load(xmlFileName); //加载XML文档
                return GetXmlNodeListByXpath(xmlDoc, xpath);
            }
            catch (Exception)
            {
                return null;
                //throw ex; //这里可以定义你自己的异常处理
            }
        }

        /// <summary>
        /// 选择匹配XPath表达式的第一个节点的匹配xmlAttributeName的属性XmlAttribute.
        /// </summary>
        /// <param name="xmlFileName">XML文档完全文件名(包含物理路径)</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名</param>
        /// <param name="xmlAttributeName">要匹配xmlAttributeName的属性名称</param>
        /// <returns>返回xmlAttributeName</returns>
        public static XmlAttribute GetXmlAttribute(this XmlDocument _xmlDocument, string xpath, string xmlAttributeName)
        {
            string content = string.Empty;
            XmlAttribute xmlAttribute = null;
            try
            {
                XmlNode xmlNode = _xmlDocument.SelectSingleNode(xpath);
                if (xmlNode != null)
                {
                    if (xmlNode.Attributes.Count > 0)
                    {
                        xmlAttribute = xmlNode.Attributes[xmlAttributeName];
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex; //这里可以定义你自己的异常处理
            }
            return xmlAttribute;
        }
        /// <summary>
        /// 选择匹配XPath表达式的第一个节点的匹配xmlAttributeName的属性XmlAttribute.
        /// </summary>
        /// <param name="xmlFileName">XML文档完全文件名(包含物理路径)</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名</param>
        /// <param name="xmlAttributeName">要匹配xmlAttributeName的属性名称</param>
        /// <returns>返回xmlAttributeName</returns>
        public static XmlAttribute GetXmlAttribute(string xmlFileName, string xpath, string xmlAttributeName)
        {
            try
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.Load(xmlFileName); //加载XML文档
                return GetXmlAttribute(xmlDoc, xpath, xmlAttributeName);
            }
            catch (Exception ex)
            {
                throw ex; //这里可以定义你自己的异常处理
            }
        }
        #endregion
        #region XmlDocument 文档节点或属性的删除
        /// <summary>
        /// 删除匹配XPath表达式的第一个节点(节点中的子元素同时会被删除)
        /// </summary>
        /// <param name="xmlDoc">XML文档</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名</param>
        /// <returns>成功返回true,失败返回false</returns>
        public static bool DeleteXmlNodeByXPath(this XmlDocument xmlDoc, string xpath)
        {
            bool isSuccess = false;
            try
            {
                if (xmlDoc == null) return isSuccess;
                XmlNode xmlNode = xmlDoc.SelectSingleNode(xpath);
                if (xmlNode != null)
                {
                    //删除节点
                    xmlNode.ParentNode.RemoveChild(xmlNode);
                }
                isSuccess = true;
            }
            catch (Exception ex)
            {
                throw ex; //这里可以定义你自己的异常处理
            }
            return isSuccess;
        }
        /// <summary>
        /// 删除匹配XPath表达式的第一个节点(节点中的子元素同时会被删除)
        /// </summary>
        /// <param name="xmlFileName">XML文档完全文件名(包含物理路径)</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名</param>
        /// <returns>成功返回true,失败返回false</returns>
        public static bool DeleteXmlNodeByXPath(string xmlFileName, string xpath)
        {
            bool isSuccess = false;
            XmlDocument xmlDoc = new XmlDocument();
            try
            {
                xmlDoc.Load(xmlFileName); //加载XML文档
                isSuccess = DeleteXmlNodeByXPath(xmlDoc, xpath);
                xmlDoc.Save(xmlFileName); //保存到XML文档
            }
            catch (Exception ex)
            {
                throw ex; //这里可以定义你自己的异常处理
            }
            return isSuccess;
        }

        /// <summary>
        /// 删除匹配XPath表达式的第一个节点中的匹配参数xmlAttributeName的属性
        /// </summary>
        /// <param name="xmlDoc">XML文档</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名</param>
        /// <param name="xmlAttributeName">要删除的xmlAttributeName的属性名称</param>
        /// <returns>成功返回true,失败返回false</returns>
        public static bool DeleteXmlAttributeByXPath(this XmlDocument xmlDoc, string xpath, string xmlAttributeName)
        {
            bool isSuccess = false;
            bool isExistsAttribute = false;
            try
            {
                if (xmlDoc == null) return isSuccess;
                XmlNode xmlNode = xmlDoc.SelectSingleNode(xpath);
                XmlAttribute xmlAttribute = null;
                if (xmlNode != null)
                {
                    //遍历xpath节点中的所有属性
                    foreach (XmlAttribute attribute in xmlNode.Attributes)
                    {
                        if (attribute.Name.ToLower() == xmlAttributeName.ToLower())
                        {
                            //节点中存在此属性
                            xmlAttribute = attribute;
                            isExistsAttribute = true;
                            break;
                        }
                    }
                    if (isExistsAttribute)
                    {
                        //删除节点中的属性
                        xmlNode.Attributes.Remove(xmlAttribute);
                    }
                }
                isSuccess = true;
            }
            catch (Exception ex)
            {
                throw ex; //这里可以定义你自己的异常处理
            }
            return isSuccess;
        }
        /// <summary>
        /// 删除匹配XPath表达式的第一个节点中的匹配参数xmlAttributeName的属性
        /// </summary>
        /// <param name="xmlFileName">XML文档完全文件名(包含物理路径)</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名</param>
        /// <param name="xmlAttributeName">要删除的xmlAttributeName的属性名称</param>
        /// <returns>成功返回true,失败返回false</returns>
        public static bool DeleteXmlAttributeByXPath(string xmlFileName, string xpath, string xmlAttributeName)
        {
            bool isSuccess = false;
            XmlDocument xmlDoc = new XmlDocument();
            try
            {
                xmlDoc.Load(xmlFileName); //加载XML文档
                isSuccess = DeleteXmlAttributeByXPath(xmlDoc, xpath, xmlAttributeName);
                xmlDoc.Save(xmlFileName); //保存到XML文档
            }
            catch (Exception ex)
            {
                throw ex; //这里可以定义你自己的异常处理
            }
            return isSuccess;
        }

        /// <summary>
        /// 删除匹配XPath表达式的第一个节点中的所有属性
        /// </summary>
        /// <param name="xmlDoc">XML文档</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名</param>
        /// <returns>成功返回true,失败返回false</returns>
        public static bool DeleteAllXmlAttributeByXPath(this XmlDocument xmlDoc, string xpath)
        {
            bool isSuccess = false;
            try
            {
                if (xmlDoc == null) return isSuccess;
                XmlNode xmlNode = xmlDoc.SelectSingleNode(xpath);
                if (xmlNode != null)
                {
                    //遍历xpath节点中的所有属性
                    xmlNode.Attributes.RemoveAll();
                }
                isSuccess = true;
            }
            catch (Exception ex)
            {
                throw ex; //这里可以定义你自己的异常处理
            }
            return isSuccess;
        }
        /// <summary>
        /// 删除匹配XPath表达式的第一个节点中的所有属性
        /// </summary>
        /// <param name="xmlFileName">XML文档完全文件名(包含物理路径)</param>
        /// <param name="xpath">要匹配的XPath表达式(例如:"//节点名//子节点名</param>
        /// <returns>成功返回true,失败返回false</returns>
        public static bool DeleteAllXmlAttributeByXPath(string xmlFileName, string xpath)
        {
            bool isSuccess = false;
            XmlDocument xmlDoc = new XmlDocument();
            try
            {
                xmlDoc.Load(xmlFileName); //加载XML文档
                isSuccess = DeleteAllXmlAttributeByXPath(xmlDoc, xpath);
                xmlDoc.Save(xmlFileName); //保存到XML文档
            }
            catch (Exception ex)
            {
                throw ex; //这里可以定义你自己的异常处理
            }
            return isSuccess;
        }
        #endregion

        #region Table2Dynamic/DataRow2Dynamic/DicToDynamic
      
        public static dynamic DicToDynamic(this IDictionary<string, object> dict)
        {
            if (dict == null || dict.Count == 0) return null;
            dynamic result = new System.Dynamic.ExpandoObject();
            foreach (var entry in dict)
            {
                (result as ICollection<KeyValuePair<string, object>>).Add(new KeyValuePair<string, object>(entry.Key, entry.Value));
            }
            return result;
        }
        public static dynamic DataRow2Dynamic(this DataRow _dr)
        {
            dynamic result = null;
            if (_dr != null && _dr.Table.Columns != null && _dr.Table.Columns.Count > 0)
            {
                result = new DynamicSerializable();// System.Dynamic.ExpandoObject();
                for (int i = 0; i < _dr.Table.Columns.Count; i++)
                {
                    // (result as ICollection<KeyValuePair<string, object>>).Add(new KeyValuePair<string, object>(_dr.Table.Columns[i].ColumnName, _dr[i].NullToStr()));
                    result.Add(_dr.Table.Columns[i].ColumnName,Fugle.Publics.BaseCode.FgFuncStr.NullToStr(_dr[i]));
                }
            }
            return result;
        }
        public static List<dynamic> Table2Dynamic(this DataTable _dt)
        {
            List<dynamic> _lsElt = new List<dynamic>();
            if (_dt != null && _dt.Rows.Count > 0)
            {
                foreach (DataRow _dr in _dt.Rows)
                {
                    var lst = _dr.DataRow2Dynamic();
                    if (lst != null)
                        _lsElt.Add(lst);
                }
            }
            return _lsElt;
        }
        public static Dictionary<string, string> XmlNodes2Dic(this System.Xml.XmlElement[] narr)
        {
            var _conditionDic = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
            if (narr != null && narr.Length > 0)
            {
                for (var i = 0; i < narr.Length; i++)
                {
                    _conditionDic[narr[i].Name] = narr[i].InnerText;
                }
            }
            return _conditionDic;
        }
        public static Dictionary<string, string> XmlNodes2Dic(this XElement[] narr)
        {
            var _conditionDic = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
            if (narr != null && narr.Length > 0)
            {
                for (var i = 0; i < narr.Length; i++)
                {
                    _conditionDic[narr[i].Name.LocalName] = narr[i].Value;
                }
            }
            return _conditionDic;
        }
        #endregion

        #region GetPropertyValue/SetPropertyValue
        /// <summary>
        /// 获取对象属性值
        /// </summary>
        /// <param name="from"></param>
        /// <param name="_to"></param>
        public static object GetPropertyValue(this Object from, string _propertyName)
        {
            try
            {
                if (from == null || string.IsNullOrEmpty(_propertyName))
                    return null;

                Type ctype = from.GetType();
                System.Reflection.PropertyInfo[] pis = ctype.GetProperties();
                foreach (System.Reflection.PropertyInfo cpi in pis)
                {
                    try
                    {
                        if (_propertyName.Trim().ToLower() == cpi.Name.Trim().ToLower())
                            return cpi.GetValue(from, null);
                    }
                    catch (Exception ex)
                    {
                       // LogUtil.Error("GetPropertyValue1," + ex.Message);
                    }
                }
                //---------------------------------------------------------------------
                System.Reflection.FieldInfo[] fis = ctype.GetFields();
                foreach (System.Reflection.FieldInfo cfi in fis)
                {
                    try
                    {
                        if (_propertyName.Trim().ToLower() == cfi.Name.Trim().ToLower())
                            return cfi.GetValue(from);
                    }
                    catch (Exception ex)
                    {
                       // LogUtil.Error("GetPropertyValue2," + ex.Message);
                    }
                }
            }
            catch (Exception ex) { //LogUtil.Error("GetPropertyValue," + ex.ToString());
                                   }
            return null;
        }

        /// <summary>
        /// 用索引化属性的可选索引值设置指定对象的该属性值  xjh 2016 8 3
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="propertyName"></param>
        /// <param name="val"></param>
        public static void SetPropertyValue(this object obj, string propertyName, object val)
        {
            if (obj == null || val == null || val == DBNull.Value || string.IsNullOrEmpty(val.ToString()) || string.IsNullOrEmpty(propertyName))
                return;
            try
            {
                System.Reflection.PropertyInfo property = obj.GetType().GetProperty(propertyName);//得到第i列的所有属性
                if (property != null)
                {
                    if (property.CanWrite)//判断对象是否为空，属性是否为空，属性是否可写！如果都为true
                    {
                        try
                        {
                            //if(!(property.PropertyType.Equals(typeof(string) || property.PropertyType.Equals(typeof(DateTime)) && .val
                            if (val.GetType().Equals(property.PropertyType))
                                property.SetValue(obj, val, null);//o对象，reader[i]对象的新值，索引器空的
                            else
                                property.SetValue(obj, Convert.ChangeType(val, property.PropertyType, null), null);
                        }
                        catch (Exception ex)
                        {
                            //LogUtil.Error("SetPropertyValue1," + ex.Message);
                        }
                    }
                }
                else
                {
                    System.Reflection.FieldInfo field = obj.GetType().GetField(propertyName);
                    if (field != null)
                    {
                        try
                        {
                            if (val.GetType().Equals(field.FieldType))
                                field.SetValue(obj, val);
                            else
                                field.SetValue(obj, Convert.ChangeType(val, field.FieldType, null));
                        }
                        catch (Exception ex)
                        {
                           // LogUtil.Error("SetPropertyValue2," + ex.Message);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                //LogUtil.Error("SetPropertyValue," + ex.Message);
            }
        }
        #endregion

        #region IsNullOrEmpty_
        ///// <summary>验证字符串是否为 null 或为空</summary>
        ///// <param name="source">要验证的字符串</param>
        ///// <returns>指示字符串是否为 null 或为空</returns>
        //public static bool IsNullOrEmpty_(this string source)
        //{
        //    return string.IsNullOrEmpty(source);
        //}
        /// <summary>
		/// 判断是否不为Null或者空
		/// </summary>
		/// <param name="obj">对象</param>
		/// <returns></returns>
		public static bool IsNotNullOrEmpty_(this object obj)
        {
            return !obj.IsNullOrEmpty_();
        }
        /// <summary>
        /// 判断是否不为Null或者空
        /// </summary>
        /// <param name="obj">对象</param>
        /// <returns></returns>
        public static bool IsNotNullOrEmpty_(this string obj)
        {
            return !obj.IsNullOrEmpty_();
        }
        /// <summary>验证字符串是否为 null 或为空</summary>
        /// <param name="source">要验证的字符串</param>
        /// <returns>指示字符串是否为 null 或为空</returns>
        public static bool IsNullOrEmpty_(this string source)
        {
            return string.IsNullOrEmpty(source) || null == source;
        }
        /// <summary>验证对象是否为 null 或数据库字段 null 值</summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="value">要验证的对象</param>
        /// <returns>指示对象是否为 null 或数据库字段 null 值</returns>
        public static bool IsNullOrEmpty_<T>(this T value)
        {
            if (value == null || Convert.IsDBNull(value))
            {
                return true;
            }
            else if (value is T[])
            {
                return (value as T[]).IsNullOrEmptyArr_();
            }
            else if (value is IEnumerable)
            {
                return (value as IEnumerable).IsNullOrEmptyArr_();
            }
            else if (value is IEnumerable<T>)
            {
                return (value as IEnumerable<T>).IsNullOrEmptyArr_();
            }
            else
            {
                string objStr = value.ToString();
                return string.IsNullOrEmpty(objStr);
            }
        }
        /// <summary>验证 GUID 是否为 null 或为空</summary>
        /// <param name="guid">要验证的 GUID</param>
        /// <returns>指示 GUID 是否为 null 或为空</returns>
        public static bool IsNullOrEmpty_(this Guid guid)
        {
            return guid == null || guid == Guid.Empty;
        }
        /// <summary>验证数组是否为 null 或为空</summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="source">要验证的数组</param>
        /// <returns>指示数组是否为 null 或为空</returns>
        public static bool IsNullOrEmptyArr_<T>(this T[] source)
        {
            return null == source || source.Length == 0;
        }
        /// <summary>验证集合是否为 null 或为空</summary>
        /// <param name="source">要验证的集合</param>
        /// <returns>指示集合是否为 null 或为空</returns>
        public static bool IsNullOrEmptyArr_(this IEnumerable source)
        {
            if (null == source) return true;
            var _source = source as ICollection;
            if (null != _source) return _source.Count == 0;
            foreach (var s in source) return false;
            return false;
        }

        /// <summary>验证集合是否为 null 或为空</summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="source">要验证的集合</param>
        /// <returns>指示集合是否为 null 或为空</returns>
        public static bool IsNullOrEmptyArr_<T>(this IEnumerable<T> source)
        {
            if (null == source) return true;

            var _source = source as ICollection<T>;
            if (null != _source) return _source.Count == 0;
            var _source2 = source as ICollection;
            if (null != _source2) return _source2.Count == 0;
            foreach (T _item in source) return false;
            return true;
        }


        /// <summary>验证是否为虚属性</summary>
        /// <param name="property">属性信息</param>
        /// <returns>指示是否为虚属性</returns>
        public static bool IsVirtual(this PropertyInfo property)
        {
            var get = property?.GetGetMethod();
            if (get != null && get.IsVirtual) return true;
            var set = property?.GetSetMethod();
            if (set != null && set.IsVirtual) return true;
            return false;
        }
        /// <summary>验证字符串是否为 null 或为空白字符串</summary>
        /// <param name="source">要验证的字符串</param>
        /// <returns>指示字符串是否为 null 或为空白字符串</returns>
        public static bool IsNullOrWhiteSpace_(this string source)
        {
            if (null == source) return true;
            for (int i = 0, len = source.Length; i < len; i++)
                if (!source[i].IsWhiteSpace_()) return false;
            return true;
        }
        /// <summary>验证字符是否属于空白字符</summary>
        /// <param name="c">要验证的字符</param>
        /// <returns>指示是否属于空白字符</returns>
        public static bool IsWhiteSpace_(this char c)
        {
            if (char.IsWhiteSpace(c)) return true;
            if (c == '﻿') return true;
            return false;
        }
        /// <summary>验证对象是否为 null</summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="source">要验证的对象</param>
        /// <returns>指示对象是否为 null</returns>
        public static bool IsNull_<T>(this T source)
        {
            return null == source;
        }

        /// <summary>验证字符串是否为空</summary>
        /// <param name="source">要验证的字符串</param>
        /// <returns>指示字符串是否为空</returns>
        public static bool IsEmpty_(this string source)
        {
            return source.Length == 0;
        }

        /// <summary>验证 GUID 是否为空</summary>
        /// <param name="guid">要验证的 GUID</param>
        /// <returns>指示 GUID 是否为空</returns>
        public static bool IsEmpty_(this Guid guid)
        {
            return guid == Guid.Empty;
        }

        /// <summary>验证集合是否为 null 或为空</summary>
        /// <param name="source">要验证的集合</param>
        /// <returns>指示集合是否为 null 或为空</returns>
        public static bool IsNullOrEmpty_(this IEnumerable source)
        {
            if (null == source) return true;
            var _source = source as ICollection;
            if (null != _source) return _source.Count == 0;
            foreach (var s in source) return false;
            return false;
        }

        /// <summary>验证集合是否为 null 或为空</summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="source">要验证的集合</param>
        /// <returns>指示集合是否为 null 或为空</returns>
        public static bool IsNullOrEmpty_<T>(this IEnumerable<T> source)
        {
            if (null == source) return true;

            var _source = source as ICollection<T>;
            if (null != _source) return _source.Count == 0;
            var _source2 = source as ICollection;
            if (null != _source2) return _source2.Count == 0;
            foreach (T _item in source) return false;
            return true;
        }

        /// <summary>验证数组是否为 null 或为空</summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="source">要验证的数组</param>
        /// <returns>指示数组是否为 null 或为空</returns>
        public static bool IsNullOrEmpty_<T>(this T[] source)
        {
            return null == source || source.Length == 0;
        }

        /// <summary>验证对象是否为数据库字段 null 值</summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="value">要验证的对象</param>
        /// <returns>指示对象是否为数据库字段 null 值</returns>
        public static bool IsDBNull_<T>(this T value)
        {
            return Convert.IsDBNull(value);
        }

        /// <summary>验证对象是否为 null 或数据库字段 null 值</summary>
        /// <typeparam name="T">数据类型</typeparam>
        /// <param name="value">要验证的对象</param>
        /// <returns>指示对象是否为 null 或数据库字段 null 值</returns>
        public static bool IsNullOrDBNull_<T>(this T value)
        {
            return null == value || Convert.IsDBNull(value);
        }
        #endregion

        #region Ext
        /// <summary>
        /// 转换为字符串,空对象转换为空字符串
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string NullToStr(this object obj)
        {
            if (obj == null || obj == System.DBNull.Value)
                return "";
            else
                return obj.ToString().Trim();
        }

        /// <summary>
        /// 为空返回字符串"null",否则返回其实际值
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string IntToStr(this int? obj)
        {
            if (obj.HasValue)
                return obj.Value.ToString();
            else
                return "null";
        }

        /// <summary>
        /// 为空返回字符串"null",否则返回其实际值
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string DecimalToStr(this decimal? obj)
        {
            if (obj.HasValue)
                return obj.Value.ToString();
            else
                return "null";
        }

        /// <summary>
        /// 转换为字符串,空对象转换为空字符串,并带单引号
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string NullToStrWithExpr(this object obj)
        {
            if (string.IsNullOrEmpty(NullToStr(obj)))
                return Expr("");
            return Expr(obj.ToString().Trim());
        }

        /// <summary>
        /// 为字符串加单引号
        /// </summary>
        /// <param name="Str">要处理的字符串</param>
        /// <returns></returns>
        public static string Expr(this string Str)
        {
            return "'" + Str.Replace("'", "''") + "'";
        }

        /// <summary>
        /// 判断是否是匿名类型
        /// </summary>
        /// <param name="obj">对象</param>
        /// <returns></returns>
        public static bool IsAnonymous(this object obj)
        {
            var type = obj.GetType();

            return Attribute.IsDefined(type, typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute), false)
                   && type.IsGenericType && type.Name.Contains("AnonymousType")
                   && (type.Name.StartsWith("<>") || type.Name.StartsWith("VB$"))
                   && type.Attributes.HasFlag(TypeAttributes.NotPublic);
        }
        /// <summary>
        /// 获取列值
        /// </summary>
        /// <param name="_dr"></param>
        /// <param name="_colName">列名</param>
        /// <returns></returns>
        public static object GetColumnValue(this DataRow _dr, string _colName, object defValue = null)
        {
            if (_dr == null || IsNullOrEmpty(_colName) || _dr.Table == null) return defValue;
            if (_dr.Table.Columns.Contains(_colName))
            {
                if (IsNullOrEmpty(_dr[_colName])) return null;
                return _dr[_colName];
            }
            return defValue;
        }
        /// <summary>
        /// 判断是否为Null或者空
        /// </summary>
        /// <param name="obj">对象</param>
        /// <returns></returns>
        public static bool IsNullOrEmpty(this object obj)
        {
            if (obj == null || obj == DBNull.Value)
            {
                return true;
            }
            else
            {
                if (obj is string)
                {
                    var objStr = obj.ToString();
                    return string.IsNullOrWhiteSpace(objStr);
                }
                return false;
            }
        }
        /// <summary>转换为相应的枚举值</summary>
        /// <typeparam name="T">枚举类型</typeparam>
        /// <param name="str">要转换的字符串</param>
        /// <param name="defval">转换不成功时的默认值</param>
        /// <returns>相应的枚举值或默认值</returns>
        public static T ToEnum_<T>(this string str, T defval = default(T)) where T : struct
        {
            if (string.IsNullOrWhiteSpace(str)) return defval;
            Type _type = typeof(T);
            if (!_type.IsEnum) return defval;
            T _retval;
            if (Enum.TryParse(str, true, out _retval))
                if (Enum.IsDefined(_type, _retval))
                    return _retval;
            return defval;
        }

        /// <summary>转换为相应的枚举值</summary>
        /// <param name="str">要转换的字符串</param>
        /// <param name="type">枚举类型</param>
        /// <returns>相应的枚举值或默认值</returns>
        public static object ToEnum_(this string str, Type type)
        {
            return Enum.Parse(type, str, true);
        }

        /// <summary>转换为相应的枚举值</summary>
        /// <typeparam name="T">枚举类型</typeparam>
        /// <param name="num">要转换的数字</param>
        /// <param name="defval">转换不成功时的默认值</param>
        /// <returns>相应的枚举值或默认值</returns>
        public static T ToEnum_<T>(this object num, T defval = default(T)) where T : struct
        {
            Type _type = typeof(T);
            if (!_type.IsEnum) return defval;
            try
            {
                T _retval = (T)Enum.ToObject(_type, num);
                if (Enum.IsDefined(_type, _retval))
                    return _retval;
                return defval;
            }
            catch { return ToEnum_(num.ToString(), defval); }
        }

        /// <summary>转换为相应的枚举值</summary>
        /// <typeparam name="T">枚举类型</typeparam>
        /// <param name="str">要转换的字符串</param>
        /// <returns>相应的枚举值或 null</returns>
        public static T? ToEnumOrNull_<T>(this string str) where T : struct
        {
            if (string.IsNullOrWhiteSpace(str)) return null;
            Type _type = typeof(T);
            if (!_type.IsEnum) return null;
            T _retval;
            if (Enum.TryParse(str, true, out _retval))
                if (Enum.IsDefined(_type, _retval))
                    return _retval;
            return null;
        }

        /// <summary>转换为相应的枚举值</summary>
        /// <param name="str">要转换的字符串</param>
        /// <param name="type">枚举类型</param>
        /// <returns>相应的枚举值或默认值</returns>
        public static object ToEnumOrNull_(this string str, Type type)
        {
            try { return Enum.Parse(type, str, true); }
            catch { return null; }
        }

        /// <summary>转换为相应的枚举值</summary>
        /// <typeparam name="T">枚举类型</typeparam>
        /// <param name="num">要转换的数字</param>
        /// <returns>相应的枚举值或 null</returns>
        public static T? ToEnumOrNull_<T>(this object num) where T : struct
        {
            Type _type = typeof(T);
            if (!_type.IsEnum) return null;
            try
            {
                T _retval = (T)Enum.ToObject(_type, num);
                if (Enum.IsDefined(_type, _retval))
                    return _retval;
                return null;
            }
            catch { return ToEnumOrNull_<T>(num.ToString()); }
        }
        #endregion

        /// <summary>
        /// 将对象转字典集合
        /// </summary>
        /// <typeparam name="TValue"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static Dictionary<string, object> ToDictionary(this object obj)
        {
            var dic = new Dictionary<string, object>();

            // 如果对象为空，则返回空字典
            if (obj == null) return dic;
            if (obj is Newtonsoft.Json.Linq.JObject _jObject)//JSON
            {
                foreach (var item in _jObject)
                {
                    var val = item.Value as Newtonsoft.Json.Linq.JValue;
                    dic[item.Key] = val != null ? val.Value : null;
                }
            }
            else if (obj is System.Dynamic.ExpandoObject _eObject)//ExpandoObject
            {
                foreach (var item in _eObject)
                {
                    dic[item.Key] = item.Value;
                }
            }
            else if (obj is System.Collections.Generic.IDictionary<string, string> _dicObjects)//Dictionary
            {
                foreach (var item in _dicObjects)
                {
                    dic[item.Key] = item.Value;
                }
            }
            else if (obj is System.Collections.Generic.IDictionary<string, object> _dicObjecto)//Dictionary
            {
                foreach (var item in _dicObjecto)
                {
                    dic[item.Key] = item.Value;
                }
            }
            else if (obj is System.Collections.IDictionary _dicObject)//IDictionary
            {
                foreach (object key in _dicObject.Keys)
                {
                    dic[key.ToString()] = _dicObject[key];
                }
            }
            else//实体
            {
                // 如果不是类类型或匿名类型，则返回空字典
                var type = obj.GetType();
                if (!(type.IsClass || IsAnonymous(type))) return dic;

                // 获取所有属性
                var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
                // 如果实例公开属性为空，则返回空字典
                if (properties.Length == 0) return dic;
                // 遍历公开属性
                foreach (var property in properties)
                {
                    var value = property.GetValue(obj, null);
                    dic[property.Name] = value;
                }
                var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
                // 如果实例公开属性为空，则返回空字典
                if (fields.Length == 0) return dic;
                // 遍历公开属性
                foreach (var field in fields)
                {
                    var value = field.GetValue(obj);
                    dic[field.Name] = value;
                }
            }
            return dic;
        }

        /// <summary>
        /// 将 DateTimeOffset 转换成 DateTime
        /// </summary>
        /// <param name="dateTime"></param>
        /// <returns></returns>
        public static DateTime ConvertToDateTime(this DateTimeOffset dateTime)
        {
            if (dateTime.Offset.Equals(TimeSpan.Zero))
                return dateTime.UtcDateTime;
            else if (dateTime.Offset.Equals(TimeZoneInfo.Local.GetUtcOffset(dateTime.DateTime)))
                return DateTime.SpecifyKind(dateTime.DateTime, DateTimeKind.Local);
            else
                return dateTime.DateTime;
        }

        /// <summary>
        /// 将 DateTime 转换成 DateTimeOffset
        /// </summary>
        /// <param name="dateTime"></param>
        /// <returns></returns>
        public static DateTimeOffset ConvertToDateTimeOffset(this DateTime dateTime)
        {
            return DateTime.SpecifyKind(dateTime, DateTimeKind.Local);
        }
        /// <summary>
        /// 将一个对象转换为指定类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static T ChangeType<T>(this object obj)
        {
            return (T)ChangeType(obj, typeof(T));
        }

        /// <summary>
        /// 将一个对象转换为指定类型
        /// </summary>
        /// <param name="obj">待转换的对象</param>
        /// <param name="type">目标类型</param>
        /// <returns>转换后的对象</returns>
        public static object ChangeType(this object obj, Type type)
        {
            if (type == null) return obj;
            if (obj == null) return type.IsValueType ? Activator.CreateInstance(type) : null;

            var underlyingType = Nullable.GetUnderlyingType(type);
            if (type.IsAssignableFrom(obj.GetType())) return obj;
            else if ((underlyingType ?? type).IsEnum)
            {
                if (underlyingType != null && string.IsNullOrEmpty(obj.ToString())) return null;
                else return Enum.Parse(underlyingType ?? type, obj.ToString());
            }
            // 处理DateTime -> DateTimeOffset 类型
            else if (obj.GetType().Equals(typeof(DateTime)) && (underlyingType ?? type).Equals(typeof(DateTimeOffset)))
            {
                return ((DateTime)obj).ConvertToDateTimeOffset();
            }
            // 处理 DateTimeOffset -> DateTime 类型
            else if (obj.GetType().Equals(typeof(DateTimeOffset)) && (underlyingType ?? type).Equals(typeof(DateTime)))
            {
                return ((DateTimeOffset)obj).ConvertToDateTime();
            }
            else if (typeof(IConvertible).IsAssignableFrom(underlyingType ?? type))
            {
                try
                {
                    return Convert.ChangeType(obj, underlyingType ?? type, null);
                }
                catch
                {
                    return underlyingType == null ? Activator.CreateInstance(type) : null;
                }
            }
            else if (type.IsClass && type != typeof(string)
                && (obj is Newtonsoft.Json.Linq.JObject
                || (obj.GetType().IsClass && obj.GetType() != typeof(string))))
            {
                return Newtonsoft.Json.JsonConvert.DeserializeObject(
                    Newtonsoft.Json.JsonConvert.SerializeObject(obj), type);
            }
            else
            {
                var converter = TypeDescriptor.GetConverter(type);
                if (converter.CanConvertFrom(obj.GetType())) return converter.ConvertFrom(obj);

                var constructor = type.GetConstructor(Type.EmptyTypes);
                if (constructor != null)
                {
                    var o = constructor.Invoke(null);
                    var propertys = type.GetProperties();
                    var oldType = obj.GetType();

                    foreach (var property in propertys)
                    {
                        var p = oldType.GetProperty(property.Name);
                        if (property.CanWrite && p != null && p.CanRead)
                        {
                            property.SetValue(o, ChangeType(p.GetValue(obj, null), property.PropertyType), null);
                        }
                    }
                    return o;
                }
            }
            return obj;
        }

        /// <summary>
        /// 获取子类型
        /// </summary>
        /// <param name="oldType"></param>
        /// <returns></returns>
        public static Type GetUnderType(this Type oldType)
        {
            bool isNullable = false;
            return GetUnderType(oldType, ref isNullable);
        }
        /// <summary>
        /// 获取子类型
        /// </summary>
        /// <param name="propertyInfo"></param>
        /// <param name="isNullable"></param>
        /// <returns></returns>
        public static Type GetUnderType(this Type oldType, ref bool isNullable)
        {
            Type unType = Nullable.GetUnderlyingType(oldType);
            isNullable = unType != null;
            return unType == null ? oldType : unType;
        }
        /// <summary>
        /// 获取子类型
        /// </summary>
        /// <param name="propertyInfo"></param>
        /// <param name="isNullable"></param>
        /// <returns></returns>
        public static Type GetUnderType(this PropertyInfo propertyInfo, ref bool isNullable)
        {
            Type unType = Nullable.GetUnderlyingType(propertyInfo.PropertyType);
            isNullable = unType != null;
            unType = unType ?? propertyInfo.PropertyType;
            return unType;
        }
        /// <summary>
        /// 获取子类型
        /// </summary>
        /// <param name="propertyInfo"></param>
        /// <returns></returns>
        public static Type GetUnderType(this PropertyInfo propertyInfo)
        {
            bool isNullable = false;
            return GetUnderType(propertyInfo, ref isNullable);
        }
        /// <summary>
        /// 支持可以赋值为null的值类型
        /// </summary>
        /// <param name="propertyInfo"></param>
        /// <returns></returns>
        public static bool IsNullable(this PropertyInfo propertyInfo)
        {
            Type unType = Nullable.GetUnderlyingType(propertyInfo.PropertyType);
            return unType != null;
        }
        /// <summary>
        /// 支持可以赋值为null的值类型
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static bool IsNullable(this Type type)
        {
            Type unType = Nullable.GetUnderlyingType(type);
            return unType != null;
        }
        /// <summary>验证是否为可 null 类型</summary>
		/// <typeparam name="T">数据类型</typeparam>
		/// <param name="value">要验证的对象</param>
		/// <returns>指示是否为可 null 类型</returns>
		public static bool IsNullable<T>(this T value)
        {
            return value?.GetType().IsNullable() == true;
        }
    }

    [Serializable]
    public class DynamicSerializable : DynamicObject, System.Runtime.Serialization.ISerializable
    {
        private readonly Dictionary<string, object> dictionary = new Dictionary<string, object>();

        public override bool TrySetMember(SetMemberBinder binder, object value)
        {
            dictionary[binder.Name] = value;

            return true;
        }
        public void Add(string binderName, object val)
        {
            dictionary[binderName] = val;
        }

        public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
        {
            foreach (var kvp in dictionary)
            {
                info.AddValue(kvp.Key, kvp.Value);
            }
        }
    }
}